#include <stdio.h>
#include <stdlib.h>
#include "Bmp24LineReader.h"
#include "Hw3Types.h"
#include "Hw3TypesExtended.h"
#include "IspImageAnalysis.h"
#include "IspImage.h"
#include "GlobalVariables.h"
#include "TestFunctions.h"
#include "SyncAndProtectionModule.h"

/*oOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoOoOoO*/
//	Internal Functions decleration
/*oOoOoOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoO*/

BOOL ConvertRowToGrayScale(int RowIndex, Byte_t *RowBuffer);

/*oOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoOoOoO*/
//	End of Internal Functions decleration
/*oOoOoOoOoOoOoOoOoOoOoOoOoOoOooOoOoOoO*/

BOOL ConvertImageToGrayScale()
{
	//variable declerations
	int RowIndex;
	BOOL SetResult;
	// allocate memory for a row buffer, into which we will read a line
	Byte_t *RowBuffer = (Byte_t*)malloc( ImageReaderAndProperties.Pitch * sizeof(Byte_t) );
	if (NULL == RowBuffer)
	{
		PrintErrorAndTerminate(ERROR_ALLOCATING_MEMORY);
		return FALSE;
	}

	// wait for running permission
	if(WaitForSingleObject(hNumOfRunningThreadsSemaphore, INFINITE) != WAIT_OBJECT_0)
	{
		PrintErrorAndTerminate(ERROR_WAITING_FOR_SINGLE_OBJECT);
		free(RowBuffer);
		return FALSE;
	}
	else
	{
		for(RowIndex = 0; RowIndex < ImageReaderAndProperties.Height ; RowIndex++)
		{
			ConvertRowToGrayScale(RowIndex, RowBuffer); 
			#ifdef DEBUG_MODE
				if (RowIndex%100 == 0)
					printf("Converted row number %d to grayscale\n", RowIndex);
			#endif

			// notify other threads that we have finished loading this line
			SetResult = SetEvent(hReadEvents[RowIndex]);
			if (FALSE == SetResult)
			{
				PrintErrorAndTerminate(ERROR_SETTING_EVENT);
				/* in case of an error we must set ALL the hReadEvents for preventing deadlocks 
				   caused by threads waiting for a successful conversion */
				for (RowIndex ; RowIndex < ImageReaderAndProperties.Height ; RowIndex++)
					SetEvent(hReadEvents[RowIndex]);
				// and then break out of the loop
				break;
			}
		}

		// clean up
		free(RowBuffer);
		// release the semaphore to allow other threads to run
		if (ReleaseSemaphore(hNumOfRunningThreadsSemaphore,1, NULL) == FALSE)
		{
			PrintErrorAndTerminate(ERROR_RELEASING_SEMAPHORE);
		}
	}
	DecreaseOpenThreadsCounter();
	return TRUE;
}


//Internal Functions
BOOL ConvertRowToGrayScale(int RowIndex, Byte_t *RowBuffer)
{
	// variable declerations
	EReadRowRes Res = SUCCESS;
	int Width = ImageReaderAndProperties.Width;
	int j;
	Bmp24LineReader Reader = ImageReaderAndProperties.Reader;

	// read the row
	Res = ReadRow( Reader, RowBuffer );
	// return if reached the end of file
	if (Res == END_OF_FILE)
		return TRUE;
	else if (Res == FAILURE)
	{
		PrintErrorAndTerminate(ERROR_READING_ROW);
		return FALSE;
	}
	
	// if we got here, reading was successful, so start converting the pixels into grayscale values
	for (j=0; j<Width ; j++) 
			Image[RowIndex][j] = ConvertPixelColorToGrayscale(RowBuffer[3*j+2], RowBuffer[3*j+1], RowBuffer[3*j]);

	return TRUE;
}
//End of Internal Functions



